package com.java.linkedlist;


import java.util.Objects;

/**
 * 单链表
 *
 * @author 19252
 */
public class SingleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode heroNode1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode heroNode2 = new HeroNode(2, "卢俊义", "玉麒麟");
        HeroNode heroNode3 = new HeroNode(3, "吴用", "智多星");
        HeroNode heroNode4 = new HeroNode(4, "公孙胜", "入云龙");
        // 创建链表
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        // 添加节点,顺序添加演示
//        singleLinkedList.addNode(heroNode1);
//        singleLinkedList.addNode(heroNode2);
//        singleLinkedList.addNode(heroNode3);
//        singleLinkedList.addNode(heroNode3);
//        singleLinkedList.addNode(heroNode4);

        // 非顺序添加，排序演示
//        singleLinkedList.addNodeByNo(heroNode4);
//        singleLinkedList.addNodeByNo(heroNode3);
//        singleLinkedList.addNodeByNo(heroNode1);
//        singleLinkedList.addNodeByNo(heroNode2);
//        singleLinkedList.addNodeByNo(heroNode2);

        // 混合添加测试
        singleLinkedList.addNode(heroNode2);
        singleLinkedList.addNode(heroNode3);
        singleLinkedList.addNodeByNo(heroNode1);
        singleLinkedList.addNode(heroNode3);
        singleLinkedList.addNode(heroNode4);
        // 链表展示
        System.out.println("================> 添加演示 <=================");
        singleLinkedList.showLinkedList();

        // 节点修改演示
        singleLinkedList.updateNode(new HeroNode(2, "玉麒麟", "卢俊义"));
        System.out.println("================> 修改演示 <=================");
        singleLinkedList.showLinkedList();

        // 节点删除演示
        singleLinkedList.deleteNode(1);
        singleLinkedList.deleteNode(2);
        singleLinkedList.deleteNode(4);
        singleLinkedList.deleteNode(1);
        singleLinkedList.deleteNode(3);
        System.out.println("================> 删除演示 <=================");
        singleLinkedList.showLinkedList();

    }
}

/**
 * 定义一个singleLinkedList 来管理 HeroNode 链表
 */
class SingleLinkedList {
    /**
     * 定义一个空的头结点
     */
    private HeroNode head = new HeroNode();

    public HeroNode getHead() {
        return head;
    }

    /**
     * 添加节点（不考虑节点的编号顺序）
     * 1. 先找到最后的一个指向为空的节点
     * 2. 再将最后的节点指向（next = new heroNode）要添加的那个节点
     */
    public void addNode(HeroNode heroNode) {
        // 首先遍历节点
        HeroNode temp = head;
        // 判断 temp.getNext() 是否为空，为空则是最后一个节点
        while (Objects.nonNull(temp.getNext())) {
            temp = temp.getNext();
            if (temp.getNo() == heroNode.getNo()){
                System.out.println("该节点已存在，不能再添加！");
                return;
            }
        }
        // 为空，再将此时的next 指向 要添加的节点
        temp.setNext(heroNode);
    }

    /**
     * 添加链表中的节点按照，no 排序
     *
     * @param heroNode 链表的节点
     */
    public void addNodeByNo(HeroNode heroNode) {
        // 首先获取链表的头结点
        HeroNode temp = head;
        // 第一结点，是否为空判断
        boolean flag = Objects.nonNull(temp.getNext());
        while (flag) {
            // 重复节点判断
            if (temp.getNo() == heroNode.getNo()) {
                System.out.println("该节点已存在，不能再添加！");
                return;
            }
            // 同时判断两个节点的no，比较，在进行插入
            // 从头结点开始
            if (temp.getNo() < heroNode.getNo() && heroNode.getNo() < temp.getNext().getNo()) {
                heroNode.setNext(temp.getNext());
                temp.setNext(heroNode);
                return;
            }
            // 头节点的下一节点
            temp = temp.getNext();
            // 判断该节点的下一节点是否为空
            flag = Objects.nonNull(temp.getNext());
        }
        // 直接置为下一节点
        temp.setNext(heroNode);
    }


    /**
     * 删除节点，根据no
     * 只要找到，被删除的节点的前一个节点，进行如下操作：
     * node.next.no = no;
     * node.next = node.next.next;
     * 完成删除
     */
    public void deleteNode(int no) {
        HeroNode temp = head;
        // 链表非空判断
        boolean flag = Objects.nonNull(temp.getNext());
        while (flag) {
            if (temp.getNext().getNo() == no) {
                temp.setNext(temp.getNext().getNext());
                return;
            }
            temp = temp.getNext();
            flag = Objects.nonNull(temp.getNext());
        }
        System.out.println("你要删除的节点不存在！");
    }

    /**
     * 修改节点
     *
     * @param heroNode 要修改的节点
     */
    public void updateNode(HeroNode heroNode) {
        HeroNode temp = head;
        boolean flag = Objects.nonNull(temp.getNext());
        while (flag) {
            temp = temp.getNext();
            if (temp.getNo() == heroNode.getNo()) {
                temp.setName(heroNode.getName());
                temp.setNickname(heroNode.getNickname());
                // 修改完毕，直接退出
                return;
            }
            // 继续循环遍历
            flag = Objects.nonNull(temp.getNext());
        }
        // 链表为空
        System.out.println("你要修改的节点不存在！");
    }

    /**
     * 遍历链表
     */
    public void showLinkedList() {
        // 判断链表是否为空
        HeroNode temp = head;
        boolean flag = Objects.isNull(temp.getNext());
        if (flag) {
            System.out.println("链表为空！");
        } else {
            temp = head.getNext();
            flag = Objects.nonNull(temp);
            while (flag) {
                System.out.println(temp);
                temp = temp.getNext();
                flag = Objects.nonNull(temp);
            }
        }
    }


}

/**
 * 每一个HeroNode 就是一个节点
 */
class HeroNode {
    /**
     * 下列字段初始值都为空
     */
    private int no;
    private String name;
    private String nickname;
    /**
     * 指向下一个节点
     */
    private HeroNode next = null;

    public HeroNode() {
    }

    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public HeroNode getNext() {
        return next;
    }

    public void setNext(HeroNode next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}
